use std::io::{self, Read};

#[derive(Debug, Clone)]
enum TokenKind {
    // Keywords
    Int, Return, If, Else, While, Break, Continue, Const, Void,
    // Identifiers & literals
    Ident(String),
    Number(String), // 始终以十进制字符串形式保存
    // Operators
    Plus, Minus, Star, Slash, Percent,
    Assign, Eq, Ne, Lt, Le, Gt, Ge,
    AndAnd, OrOr, Not,
    // Delimiters
    LParen, RParen, LBrace, RBrace, LBracket, RBracket,
    Comma, Semicolon,
}

#[derive(Debug, Clone)]
struct Token {
    kind: TokenKind,
    line: usize,
    text: String, // 打印时使用（数字常量已转成十进制文本）
}

#[derive(Debug, Clone)]
struct LexError {
    line: usize,
    msg: String,
}

struct Lexer {
    src: Vec<char>,
    pos: usize,
    line: usize,
}

impl Lexer {
    fn new(input: &str) -> Self {
        Self { src: input.chars().collect(), pos: 0, line: 1 }
    }

    fn peek(&self) -> Option<char> { self.src.get(self.pos).copied() }
    fn peek2(&self) -> Option<char> { self.src.get(self.pos + 1).copied() }

    fn bump(&mut self) -> Option<char> {
        let ch = self.src.get(self.pos).copied();
        if let Some(c) = ch {
            self.pos += 1;
            if c == '\n' { self.line += 1; }
        }
        ch
    }

    fn match_char(&mut self, expected: char) -> bool {
        if self.peek() == Some(expected) { self.pos += 1; if expected=='\n'{self.line+=1;} true } else { false }
    }

    fn skip_ws_and_comments(&mut self, errors: &mut Vec<LexError>) {
        loop {
            // 跳过空白
            while let Some(c) = self.peek() {
                if c == ' ' || c == '\t' || c == '\r' || c == '\n' { self.bump(); } else { break; }
            }
            // 注释：//... / * ... * /
            if self.peek() == Some('/') && self.peek2() == Some('/') {
                // 行注释
                while let Some(c) = self.bump() { if c == '\n' { break; } }
                continue;
            }
            if self.peek() == Some('/') && self.peek2() == Some('*') {
                // 块注释（不支持嵌套）
                let start_line = self.line;
                self.bump(); self.bump(); // consume '/*'
                let mut found = false;
                while let Some(c) = self.bump() {
                    if c == '*' && self.peek() == Some('/') {
                        self.bump(); // consume '/'
                        found = true;
                        break;
                    }
                }
                if !found {
                    errors.push(LexError{ line: start_line, msg: "unterminated block comment".to_string()});
                }
                continue;
            }
            break;
        }
    }

    fn lex_ident_or_kw(&mut self) -> TokenKind {
        let start = self.pos;
        self.bump();
        while let Some(c) = self.peek() {
            if c.is_ascii_alphanumeric() || c == '_' { self.bump(); } else { break; }
        }
        let s: String = self.src[start..self.pos].iter().collect();
        match s.as_str() {
            "int" => TokenKind::Int,
            "return" => TokenKind::Return,
            "if" => TokenKind::If,
            "else" => TokenKind::Else,
            "while" => TokenKind::While,
            "break" => TokenKind::Break,
            "continue" => TokenKind::Continue,
            "const" => TokenKind::Const,
            "void" => TokenKind::Void,
            _ => TokenKind::Ident(s),
        }
    }

    fn lex_number(&mut self, errors: &mut Vec<LexError>) -> (TokenKind, String) {
        let line_at = self.line;
        let start_pos = self.pos;
        
        if self.peek() == Some('0') {
            // 处理以0开头的数字
            if self.peek2() == Some('x') || self.peek2() == Some('X') {
                // 十六进制: 0x...
                self.bump(); self.bump(); // 消费 0x
                let hex_start = self.pos;
                while let Some(c) = self.peek() {
                    if c.is_ascii_hexdigit() {
                        self.bump();
                    } else {
                        break;
                    }
                }
                if self.pos == hex_start {
                    errors.push(LexError{ line: line_at, msg: "invalid hex literal: missing digits".into()});
                    return (TokenKind::Number("0".into()), "0".into());
                }
                let hex_str: String = self.src[hex_start..self.pos].iter().collect();
                let val = u128::from_str_radix(&hex_str, 16).unwrap_or(0);
                (TokenKind::Number(val.to_string()), val.to_string())
            } else {
                // 处理 0 或 0... (前导零的十进制)
                self.bump(); // 消费第一个0
                let mut has_digits = false;
                let mut has_invalid_octal = false;
                
                // 检查后续数字
                while let Some(c) = self.peek() {
                    if c.is_ascii_digit() {
                        if c >= '8' {
                            has_invalid_octal = true;
                            break; // 遇到无效八进制数字，停止
                        }
                        self.bump();
                        has_digits = true;
                    } else {
                        break;
                    }
                }
                
                if !has_digits {
                    // 只有一个0
                    return (TokenKind::Number("0".into()), "0".into());
                }
                
                if has_invalid_octal {
                    // 遇到无效八进制数字，只返回0，后续数字会在下次调用中处理
                    self.pos = start_pos + 1; // 重置位置到只消费了0
                    return (TokenKind::Number("0".into()), "0".into());
                }
                
                // 有效的八进制数字，按八进制处理
                let oct_str: String = self.src[start_pos + 1..self.pos].iter().collect();
                let val = u128::from_str_radix(&oct_str, 8).unwrap_or(0);
                (TokenKind::Number(val.to_string()), val.to_string())
            }
        } else {
            // 十进制数字
            while let Some(c) = self.peek() {
                if c.is_ascii_digit() {
                    self.bump();
                } else {
                    break;
                }
            }
            let num_str: String = self.src[start_pos..self.pos].iter().collect();
            let val = num_str.parse::<u128>().unwrap_or(0);
            (TokenKind::Number(val.to_string()), val.to_string())
        }
    }

    fn next_token(&mut self, errors: &mut Vec<LexError>) -> Option<Token> {
        self.skip_ws_and_comments(errors);
        let ch = self.peek()?;
        let line = self.line;

        // Ident or keyword
        if ch.is_ascii_alphabetic() || ch == '_' {
            let kind = self.lex_ident_or_kw();
            let text = match &kind {
                TokenKind::Ident(s) => s.clone(),
                TokenKind::Int => "int".into(),
                TokenKind::Return => "return".into(),
                TokenKind::If => "if".into(),
                TokenKind::Else => "else".into(),
                TokenKind::While => "while".into(),
                TokenKind::Break => "break".into(),
                TokenKind::Continue => "continue".into(),
                TokenKind::Const => "const".into(),
                TokenKind::Void => "void".into(),
                _ => unreachable!(),
            };
            return Some(Token{ kind, line, text });
        }

        // Number
        if ch.is_ascii_digit() {
            let (kind, text) = self.lex_number(errors);
            return Some(Token{ kind, line, text });
        }

        // Operators / delimiters
        let tok = match ch {
            '+' => { self.bump(); TokenKind::Plus }
            '-' => { self.bump(); TokenKind::Minus }
            '*' => { self.bump(); TokenKind::Star }
            '/' => { self.bump(); TokenKind::Slash }
            '%' => { self.bump(); TokenKind::Percent }
            '!' => {
                self.bump();
                if self.peek() == Some('=') { self.bump(); TokenKind::Ne } else { TokenKind::Not }
            }
            '=' => { self.bump(); if self.peek()==Some('='){ self.bump(); TokenKind::Eq } else { TokenKind::Assign } }
            '<' => { self.bump(); if self.peek()==Some('='){ self.bump(); TokenKind::Le } else { TokenKind::Lt } }
            '>' => { self.bump(); if self.peek()==Some('='){ self.bump(); TokenKind::Ge } else { TokenKind::Gt } }
            '&' => { self.bump(); if self.peek()==Some('&'){ self.bump(); TokenKind::AndAnd } else { 
                // 不支持单个 &，报错但继续
                let msg = "unsupported token '&' (use &&)".to_string();
                // 记录错误并返回占位 token 以继续
                // 这里返回 Not 只是占位，外面只在无错误时打印 token
                // 真正的错误会让最终只打印错误列表
                // 也可返回 None 直接跳过
                return { errors.push(LexError{ line, msg }); self.next_token(errors) };
            } }
            '|' => { self.bump(); if self.peek()==Some('|'){ self.bump(); TokenKind::OrOr } else {
                let msg = "unsupported token '|' (use ||)".to_string();
                return { errors.push(LexError{ line, msg }); self.next_token(errors) };
            } }
            '(' => { self.bump(); TokenKind::LParen }
            ')' => { self.bump(); TokenKind::RParen }
            '{' => { self.bump(); TokenKind::LBrace }
            '}' => { self.bump(); TokenKind::RBrace }
            '[' => { self.bump(); TokenKind::LBracket }
            ']' => { self.bump(); TokenKind::RBracket }
            ',' => { self.bump(); TokenKind::Comma }
            ';' => { self.bump(); TokenKind::Semicolon }
            _ => {
                let msg = format!("invalid character: '{}'", ch);
                self.bump();
                errors.push(LexError{ line, msg });
                return self.next_token(errors);
            }
        };

        let text = match tok {
            TokenKind::Plus => "+".into(),
            TokenKind::Minus => "-".into(),
            TokenKind::Star => "*".into(),
            TokenKind::Slash => "/".into(),
            TokenKind::Percent => "%".into(),
            TokenKind::Assign => "=".into(),
            TokenKind::Eq => "==".into(),
            TokenKind::Ne => "!=".into(),
            TokenKind::Lt => "<".into(),
            TokenKind::Le => "<=".into(),
            TokenKind::Gt => ">".into(),
            TokenKind::Ge => ">=".into(),
            TokenKind::AndAnd => "&&".into(),
            TokenKind::OrOr => "||".into(),
            TokenKind::Not => "!".into(),
            TokenKind::LParen => "(".into(),
            TokenKind::RParen => ")".into(),
            TokenKind::LBrace => "{".into(),
            TokenKind::RBrace => "}".into(),
            TokenKind::LBracket => "[".into(),
            TokenKind::RBracket => "]".into(),
            TokenKind::Comma => ",".into(),
            TokenKind::Semicolon => ";".into(),
            TokenKind::Ident(_) | TokenKind::Number(_) | TokenKind::Int | TokenKind::Return | TokenKind::If | TokenKind::Else | TokenKind::While | TokenKind::Break | TokenKind::Continue | TokenKind::Const | TokenKind::Void => unreachable!(),
        };
        Some(Token{ kind: tok, line, text })
    }
}

fn print_tokens_or_errors(tokens: Vec<Token>, errors: Vec<LexError>) {
    if !errors.is_empty() {
        for e in errors {
            eprintln!("Error type A at Line {}:{}", e.line, e.msg);
        }
    } else {
        for t in tokens {
            match &t.kind {
                TokenKind::Ident(_) => eprintln!("IDENT {} at Line {}.", t.text, t.line),
                TokenKind::Number(_) => eprintln!("INTEGER_CONST {} at Line {}.", t.text, t.line),
                TokenKind::Int => eprintln!("INT int at Line {}.", t.line),
                TokenKind::Return => eprintln!("RETURN return at Line {}.", t.line),
                TokenKind::If => eprintln!("IF if at Line {}.", t.line),
                TokenKind::Else => eprintln!("ELSE else at Line {}.", t.line),
                TokenKind::While => eprintln!("WHILE while at Line {}.", t.line),
                TokenKind::Break => eprintln!("BREAK break at Line {}.", t.line),
                TokenKind::Continue => eprintln!("CONTINUE continue at Line {}.", t.line),
                TokenKind::Const => eprintln!("CONST const at Line {}.", t.line),
                TokenKind::Void => eprintln!("VOID void at Line {}.", t.line),
                TokenKind::Plus => eprintln!("PLUS + at Line {}.", t.line),
                TokenKind::Minus => eprintln!("MINUS - at Line {}.", t.line),
                TokenKind::Star => eprintln!("MUL * at Line {}.", t.line),
                TokenKind::Slash => eprintln!("DIV / at Line {}.", t.line),
                TokenKind::Percent => eprintln!("MOD % at Line {}.", t.line),
                TokenKind::Assign => eprintln!("ASSIGN = at Line {}.", t.line),
                TokenKind::Eq => eprintln!("EQ == at Line {}.", t.line),
                TokenKind::Ne => eprintln!("NEQ != at Line {}.", t.line),
                TokenKind::Lt => eprintln!("LT < at Line {}.", t.line),
                TokenKind::Le => eprintln!("LE <= at Line {}.", t.line),
                TokenKind::Gt => eprintln!("GT > at Line {}.", t.line),
                TokenKind::Ge => eprintln!("GE >= at Line {}.", t.line),
                TokenKind::AndAnd => eprintln!("AND && at Line {}.", t.line),
                TokenKind::OrOr => eprintln!("OR || at Line {}.", t.line),
                TokenKind::Not => eprintln!("NOT ! at Line {}.", t.line),
                TokenKind::LParen => eprintln!("L_PAREN ( at Line {}.", t.line),
                TokenKind::RParen => eprintln!("R_PAREN ) at Line {}.", t.line),
                TokenKind::LBrace => eprintln!("L_BRACE {{ at Line {}.", t.line),
                TokenKind::RBrace => eprintln!("R_BRACE }} at Line {}.", t.line),
                TokenKind::LBracket => eprintln!("L_BRACKT [ at Line {}.", t.line),
                TokenKind::RBracket => eprintln!("R_BRACKT ] at Line {}.", t.line),
                TokenKind::Comma => eprintln!("COMMA , at Line {}.", t.line),
                TokenKind::Semicolon => eprintln!("SEMICOLON ; at Line {}.", t.line),
            }
        }
    }
}

fn main() {
    // 读取全部 stdin
    let mut input = String::new();
    io::stdin().read_to_string(&mut input).expect("read stdin failed");

    let mut lexer = Lexer::new(&input);
    let mut tokens = Vec::new();
    let mut errors = Vec::new();

    while let Some(tok) = lexer.next_token(&mut errors) { tokens.push(tok); }

    print_tokens_or_errors(tokens, errors);
}
